/* * Copyright 2010-2017 Boxfuse GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.flywaydb.core.internal.util.scanner.classpath; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; import java.io.IOException; import java.net.URL; import java.util.Enumeration; import java.util.Set; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * OSGi specific scanner that performs the migration search in * the current bundle's classpath. * * <p> * The resources that this scanner returns can only be loaded if * Flyway's ClassLoader has access to the bundle that contains the migrations. * </p> */ public class OsgiClassPathLocationScanner implements ClassPathLocationScanner { //Felix and Equinox "host" resource url pattern starts with bundleId, which is // long according osgi core specification private static final Pattern bundleIdPattern = Pattern.compile("^\\d+"); public Set<String> findResourceNames(String location, URL locationUrl) throws IOException { Set<String> resourceNames = new TreeSet<String>(); Bundle bundle = getTargetBundleOrCurrent(FrameworkUtil.getBundle(getClass()), locationUrl); @SuppressWarnings({"unchecked"}) Enumeration<URL> entries = bundle.findEntries(locationUrl.getPath(), "*", true); if (entries != null) { while (entries.hasMoreElements()) { URL entry = entries.nextElement(); String resourceName = getPathWithoutLeadingSlash(entry); resourceNames.add(resourceName); } } return resourceNames; } private Bundle getTargetBundleOrCurrent(Bundle currentBundle, URL locationUrl) { try { Bundle targetBundle = currentBundle.getBundleContext().getBundle(getBundleId(locationUrl.getHost())); return targetBundle != null ? targetBundle : currentBundle; } catch (Exception e) { return currentBundle; } } private long getBundleId(String host) { final Matcher matcher = bundleIdPattern.matcher(host); if (matcher.find()) { return Double.valueOf(matcher.group()).longValue(); } throw new IllegalArgumentException("There's no bundleId in passed URL"); } private String getPathWithoutLeadingSlash(URL entry) { final String path = entry.getPath(); return path.startsWith("/") ? path.substring(1) : path; } }